package com.zzj.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zzj.base.Result;
import com.zzj.entity.*;
import com.zzj.handle.WebSocket;
import com.zzj.model.dto.QueryListDTO;
import com.zzj.model.dto.comment.CommentListDTO;
import com.zzj.model.dto.comment.CommentReplyCreateDTO;
import com.zzj.model.dto.comment.CommentRootCreateDTO;
import com.zzj.model.vo.CommentVo;
import com.zzj.service.*;
import com.zzj.utils.JWTUtil;
import com.zzj.utils.QueryUtil;
import com.zzj.utils.RedisUtil;
import com.zzj.utils.Utils;
import jakarta.annotation.Resource;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zzj
 * @since 2023-03-18
 */
@RestController
@RequestMapping("/comment")
public class CommentController {


    @Resource
    private ICommentRootService commentRootService;
    @Resource
    private ICommentReplyService commentReplyService;
    @Resource
    private IArticleService articleService;
    @Resource
    private RedisService redisService;
    @Resource
    private WebSocket webSocket;
    @Resource
    private ILikeService likeService;


    /**
     * 评论列表
     * 包含回复
     * 是否点赞
     *
     * @param token
     * @param in
     * @return
     */
    @PostMapping("commentList")
    public Result commentList(@RequestHeader(value = "Authorization") String token,
                              @RequestBody @Validated CommentListDTO in) {
        IPage<CommentVo> commentVoIPage = commentRootService.commentVoList(new Page<>(in.getPageNo(), in.getPageSize()), in);
        List<CommentVo> commentVoList = commentVoIPage.getRecords();
        String username = JWTUtil.getUsername(token);
        String likeCommentRootId = redisService.getLikeCommentRootId(username);
        if (likeCommentRootId != null && !likeCommentRootId.equals("")) {
            String[] split = likeCommentRootId.split(",");
            List<String> reads = Arrays.asList(split);
            List<CommentVo> list = commentVoList.stream()
                    .map(commentVo -> reads.stream()
                            .filter(str -> commentVo.getId() == Integer.parseInt(str))
                            .findFirst()
                            .map(str -> {

                                commentVo.setIsLike(1);
                                return commentVo;
                            }).orElse(commentVo)).toList();
        }
        commentVoIPage.setRecords(commentVoList);
        return Result.success(commentVoIPage);
    }

    /**
     * 评论列表
     * 是否已读
     *
     * @param token
     * @param in
     * @return
     */
    @PostMapping("commentRootQueryList")
    public Result commentRootQueryList(@RequestHeader(value = "Authorization") String token,
                                       @RequestBody @Validated QueryListDTO in) {
        QueryWrapper<CommentRoot> queryWrapper = QueryUtil.paramsWrapper(in.getAndParams(), in.getOrParams(), in.getOrderParams());
        Page<CommentRoot> commentRootPage = new Page<>(in.getPageNo(), in.getPageSize());
        IPage<CommentRoot> commentRootIPage = commentRootService.getBaseMapper().selectPage(commentRootPage, queryWrapper);
        List<CommentRoot> commentRoots = commentRootIPage.getRecords();
        String username = JWTUtil.getUsername(token);
        String commentNoReadId = redisService.getCommentNoReadId(username);
        if (commentNoReadId != null && !commentNoReadId.equals("")) {
            List<String> noReads = Utils.stringToList(commentNoReadId, ",");
            List<CommentRoot> list = commentRoots.stream()
                    .map(commentRoot -> noReads.stream()
                            .filter(str -> commentRoot.getId() == Integer.parseInt(str))
                            .findFirst()
                            .map(str -> {
                                commentRoot.setIsRead(0);
                                return commentRoot;
                            }).orElse(commentRoot)).toList();
        }
        commentRootIPage.setRecords(commentRoots);
        return Result.success(commentRootIPage);
    }

    /**
     * 回复列表
     * 是否已读
     *
     * @param token
     * @param in
     * @return
     */
    @PostMapping("commentReplyQueryList")
    public Result commentReplyQueryList(@RequestHeader(value = "Authorization") String token,
                                        @RequestBody @Validated QueryListDTO in) {

        QueryWrapper<CommentReply> queryWrapper = QueryUtil.paramsWrapper(in.getAndParams(), in.getOrParams(), in.getOrderParams());
        Page<CommentReply> commentReplyPage = new Page<>(in.getPageNo(), in.getPageSize());
        IPage<CommentReply> commentReplyIPage = commentReplyService.getBaseMapper().selectPage(commentReplyPage, queryWrapper);
        List<CommentReply> commentRoots = commentReplyIPage.getRecords();
        String username = JWTUtil.getUsername(token);
        String replyNoReadId = redisService.getReplyNoReadId(username);
        if (replyNoReadId != null && !replyNoReadId.equals("")) {
            String[] split = replyNoReadId.split(",");
            List<String> noReads = Arrays.asList(split);
            List<CommentReply> list = commentRoots.stream()
                    .map(commentReply -> noReads.stream()
                            .filter(str -> commentReply.getId() == Integer.parseInt(str))
                            .findFirst()
                            .map(str -> {
                                commentReply.setIsRead(0);
                                return commentReply;
                            }).orElse(commentReply)).toList();
        }
        commentReplyIPage.setRecords(commentRoots);
        return Result.success(commentReplyIPage);
    }

    /**
     * 创建评论
     * 推送未读 缓存未读
     *
     * @param in
     * @return
     * @throws IOException
     */
    @Transactional
    @PostMapping("createCommentRoot")
    public Result createCommentRoot(@RequestBody @Validated CommentRootCreateDTO in) throws IOException {
        CommentRoot commentRoot = JSONObject.parseObject(JSON.toJSONString(in), CommentRoot.class);
        commentRootService.save(commentRoot);
        /**
         * 文章 评论数量增加
         */
        if (in.getTargetType() == 2) {
            articleService.lambdaUpdate()
                    .eq(Article::getId, in.getTargetId())
                    .setSql("comment_count = comment_count + 1").update();
        }
        /**
         * 评论数量增加 或缓存
         */
        webSocket.sendComment(in.getToUsername(), commentRoot.getId());
        return Result.success(commentRoot);
    }

    /**
     * 创建回复
     * 推动未读 缓存未读
     *
     * @param in
     * @return
     * @throws IOException
     */
    @Transactional
    @PostMapping("createCommentReply")
    public Result createCommentReply(@RequestBody @Validated CommentReplyCreateDTO in) throws IOException {
        CommentReply commentReply = JSONObject.parseObject(JSON.toJSONString(in), CommentReply.class);

        CommentRoot one = commentRootService.getOne(Wrappers.<CommentRoot>lambdaQuery()
                        .eq(CommentRoot::getId, in.getRootId()),
                false);
        commentReplyService.save(commentReply);
        /**
         * 文章 评论数量增加
         */
        if (one.getTargetType() == 2) {
            articleService.lambdaUpdate()
                    .eq(Article::getId, one.getTargetId())
                    .setSql("comment_count = comment_count + 1").update();
        }

        /**
         * 评论数量增加 或缓存
         */
        webSocket.sendReply(in.getToUsername(), commentReply.getId());
        return Result.success();
    }

    /**
     * 点赞评论  取消点赞
     *
     * @param token
     * @param id
     * @param toUsername
     * @return
     * @throws IOException
     */
    @Transactional
    @PostMapping("likeCommentRoot")
    public Result likeCommentRoot(@RequestHeader(value = "Authorization") String token,
                                  @RequestParam int id, @RequestParam String toUsername) throws IOException {
        String username = JWTUtil.getUsername(token);
        String likeCommentRootId = redisService.getLikeCommentRootId(username);
        if (likeCommentRootId != null) {
            String[] split = likeCommentRootId.split(",");
            List<String> likeArticleIds = Arrays.asList(split);
            //取消点赞
            if (likeArticleIds.contains(String.valueOf(id))) {
                commentRootService.lambdaUpdate()
                        .eq(CommentRoot::getId, id)
                        .setSql("like_count = like_count - 1").update();
                likeCommentRootId = likeCommentRootId.replace(id + ",", "");
                Like one = likeService.findLike(id, username);
                likeService.remove(id, username);
                webSocket.sendCancelLike(toUsername, one.getId());
            } else {
                //点赞
                commentRootService.lambdaUpdate()
                        .eq(CommentRoot::getId, id)
                        .setSql("like_count = like_count + 1").update();
                likeCommentRootId += id + ",";
                Like like = likeService.save(id, 3, username, toUsername);
                webSocket.sendLike(toUsername, like.getId());
            }
            redisService.setLikeCommentRootId(username, likeCommentRootId);
        } else {
            //点赞
            redisService.setLikeCommentRootId(username, id + ",");
            commentRootService.lambdaUpdate()
                    .eq(CommentRoot::getId, id)
                    .setSql("like_count = like_count + 1").update();
            Like like = likeService.save(id, 3, username, toUsername);
            webSocket.sendLike(toUsername, like.getId());
        }
        return Result.success("操作成功");
    }


    /**
     * id查询评论
     *
     * @param id
     * @return
     */
    @PostMapping("id")
    public Result id(@RequestParam int id) {
        CommentRoot commentRoot = commentRootService.findCommentRoot(id);
        return Result.success(commentRoot);
    }

    /**
     * 查询评论
     * 预约评价
     *
     * @param targetId     评论事物ID
     * @param targetType   评论事物类型
     * @param fromUsername 评论人
     * @param toUsername   评论事物作者
     * @return
     */
    @PostMapping("queryByTargetIdBothUsername")
    public Result queryByTargetIdBothUsername(@RequestParam int targetId,
                                              @RequestParam int targetType,
                                              @RequestParam String fromUsername,
                                              @RequestParam String toUsername) {
        List<CommentRoot> list = commentRootService.lambdaQuery()
                .eq(CommentRoot::getTargetId, targetId)
                .eq(CommentRoot::getTargetType, targetType)
                .eq(CommentRoot::getFromUsername, fromUsername)
                .eq(CommentRoot::getToUsername, toUsername).list();
        return Result.success(list);
    }

    /**
     * 医护主页 评论评价
     *
     * @param targetType
     * @param toUsername
     * @return
     */
    @PostMapping("queryByToUsername")
    public Result queryByToUsername(@RequestParam int targetType,
                                    @RequestParam String toUsername) {
        List<CommentRoot> list = commentRootService.lambdaQuery()
                .eq(CommentRoot::getTargetType, targetType)
                .eq(CommentRoot::getToUsername, toUsername).list();
        return Result.success(list);
    }

    /**
     * 查看评论
     * 消除已读
     *
     * @param token
     * @param id
     * @return
     */
    @Transactional
    @PostMapping("commentRootReadById")
    public Result commentRootReadById(@RequestHeader(value = "Authorization") String token,
                                      @RequestParam int id) {
        String username = JWTUtil.getUsername(token);
        String commentNoReadId = redisService.getCommentNoReadId(username);
        if (commentNoReadId != null) {
            if (Utils.stringIsContainStrSplit(commentNoReadId, String.valueOf(id), ",")) {
                redisService.setCommentNoReadId(username, commentNoReadId.replace(id + ",", ""));
            }
        }
        CommentVo one = commentRootService.id(id);
        String likeCommentRootId = redisService.getLikeCommentRootId(username);
        if (likeCommentRootId != null) {
            if (Utils.stringIsContainStrSplit(likeCommentRootId, String.valueOf(id), ",")) {
                one.setIsLike(1);
            }
        }
        return Result.success(one);
    }

    /**
     * 查看回复
     * 消除已读
     * 获取到根评论
     *
     * @param token
     * @param id
     * @return
     */
    @Transactional
    @PostMapping("commentReplyReadById")
    public Result commentReplyReadById(@RequestHeader(value = "Authorization") String token,
                                       @RequestParam int id) {
        String username = JWTUtil.getUsername(token);
        String replyNoReadId = redisService.getReplyNoReadId(username);
        if (replyNoReadId != null) {
            if (Utils.stringIsContainStrSplit(replyNoReadId, String.valueOf(id), ",")) {
                redisService.setReplyNoReadId(username, replyNoReadId.replace(id + ",", ""));
            }
        }
        CommentReply one = commentReplyService.find(id);
        CommentVo commentVo = commentRootService.id(one.getRootId());
        return Result.success(commentVo);
    }

    /**
     * 获取未读评论数量
     *
     * @param token
     * @return
     */
    @PostMapping("getCommentNoReadNum")
    public Result getCommentNoReadNum(@RequestHeader(value = "Authorization") String token) {
        String username = JWTUtil.getUsername(token);
        String commentNoReadId = redisService.getCommentNoReadId(username);
        if (commentNoReadId != null && commentNoReadId != "") {
            return Result.success(commentNoReadId.split(",").length);
        }
        return Result.success(0);
    }

    /**
     * 获取未读回复数量
     *
     * @param token
     * @return
     */
    @PostMapping("getReplyNoReadNum")
    public Result getReplyNoReadNum(@RequestHeader(value = "Authorization") String token) {
        String username = JWTUtil.getUsername(token);
        String replyNoReadId = redisService.getReplyNoReadId(username);
        if (replyNoReadId != null && replyNoReadId != "") {
            return Result.success(replyNoReadId.split(",").length);
        }
        return Result.success(0);
    }


    /**
     * 删除评论 及其所有回复
     *
     * @param id
     * @return
     */
    @Transactional
    @PostMapping("removeCommentById")
    public Result removeCommentById(@RequestParam int id) {
        boolean remove = commentRootService.lambdaUpdate()
                .eq(CommentRoot::getId, id)
                .remove();
        boolean remove1 = commentReplyService.lambdaUpdate()
                .eq(CommentReply::getRootId, id)
                .remove();
        if (remove && remove1) {
            return Result.success("删除成功");
        }
        return Result.error("删除失败");
    }

    /**
     * 删除回复
     *
     * @param id
     * @return
     */
    @PostMapping("removeReplyById")
    public Result removeReplyById(@RequestParam int id) {
        boolean remove = commentReplyService.lambdaUpdate()
                .eq(CommentReply::getId, id)
                .remove();
        if (!remove) {
            return Result.error("删除失败");
        }
        return Result.success("删除成功");
    }
}
